package dk.ahp.getmeoff;

import java.io.File;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import android.location.Location;
import android.os.AsyncTask;
import android.util.Log;

/**
 * This class contains all stored destinations.
 */
public class DestinationLogic {
	private static final String TAG = DestinationLogic.class.getSimpleName();
	private DBHelper dbHelper;
	private Map<Long, Destination> destinations = new HashMap<Long, Destination>();
	
	/**
	 * Læser data fra database og opbygger datastruktur 
	 * @param dbDir Directory hvor databasen skal placeres eller er placeret.
	 */
	DestinationLogic(File dbDir) {
		dbHelper = new DBHelper(GetMeOffApplication.getMeOffApplication, dbDir + "/Destiantions.db");
		
		List<Destination> dests = dbHelper.getAllDestinations();
		if (0 == dests.size()) {
			dbHelper.AddTestData();// Opbyg noget test data.	
			dests = dbHelper.getAllDestinations(); // og prøv igen
		}
		
		for (Destination d : dests) {
			if(!destinations.containsKey(d.getId())){
				destinations.put(d.getId(), d);
				//hvis vi kun har lat long, så find en addresse
				if((null == d.getDestAddress() || "".equals(d.getDestAddress())) && null != d.getDestination()) {
					FindAddress fd = new FindAddress(d.getId(), true);
					fd.execute(d.getDestination());
				}
				if((null == d.getStartAddress() || "".equals(d.getStartAddress())) && null != d.getStart()) {
					FindAddress fd = new FindAddress(d.getId(), false);
					fd.execute(d.getDestination());
				}
			}
		}
		
		Log.d(TAG, "DestinationLogic created");
	}
	
	/**
	 * This class retrieves address information for a Lat/Lon location. 
	 */
	class FindAddress extends AsyncTask<Location, Void, String> {
		private Long destId;
		private Boolean findDest;

		public FindAddress(Long destinationId, Boolean findDest) {
			super();
			destId = destinationId;
			this.findDest = findDest;
		}
		@Override
		protected String doInBackground(Location... params) {
			String res = Destination.locationToAddres(params[0], false);
			return res;
		}
		
		@Override
		protected void onPostExecute(String resultat) {
			if (null != resultat) {
				Destination tmpDestination = destinations.get(destId);
				if(findDest) {
					tmpDestination.setDestAddress(resultat);
				} else {
					tmpDestination.setStartAddress(resultat);
				}
				SaveDestination(tmpDestination);
			}
		}
	}
	
	/**
	 * @return A list of destination names.
	 */
	Set<String> getDestinationNames() {
		Set<String> res = new HashSet<String>();
		for (Long i : destinations.keySet()) {
			res.add(destinations.get(i).getName());
		}
		return res;
	}
	
	/**
	 * Finds and returns Destination named name.
	 * @param name Name of Destination to find.
	 * @return Destination or null if no Destination is found.
	 */
	Destination getDestination(String name) {
		for (Long i : destinations.keySet()) {
			String tmpName = destinations.get(i).getName();
			if (name.equals(tmpName)) {
				return destinations.get(i);
			}
		}
		return null;
	}
	
	/**
	 * Adds Destination to database and Destination list. 
	 * @param dest Destination to save.
	 * @return True if Destination was successfully added.
	 */
	Boolean AddDestination(Destination dest) {
		Boolean res = dbHelper.AddDestination(dest);
		if(res && !destinations.containsKey(dest.getId())){
			destinations.put(dest.getId(), dest);
			return true;
		}
		return false;
	}
	
	/**
	 * Saves dest (either updates if it exists or adds it if it is new).
	 * @param dest Destination to save.
	 * @return True if Destination was successfully added.
	 */
	Boolean SaveDestination(Destination dest) {
		Boolean res = false;
		if (destinations.containsKey(dest.getId())) { // update
			destinations.put(dest.getId(), dest);
			res = dbHelper.UpdateDestination(dest);
			return res;
		}
		// ny destination,
		res = AddDestination(dest);
		
		return res;
	}

	public Boolean Delete(String distName) {
		Destination dest = getDestination(distName);
		Boolean res = dbHelper.Delete(dest);
		if(res && destinations.containsKey(dest.getId())){
			destinations.remove(dest.getId());
			return true;
		}
		return false;
	}
	

}
